package com.laker.autotest.common.reporters;

import com.laker.autotest.common.utils.TestNGUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.testng.*;
import org.testng.xml.XmlSuite;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 自定义的 EasyHtmlV2Reporter 类，用于生成商务风格的 HTML 测试报告。
 * 该报告包含测试结果的详细信息，有饼图和表格展示测试结果，适合本地化展示。
 * 优化点：
 * 1. 结构清晰，便于扩展。
 * 2. 生成时间、统计数据、详细用例一目了然。
 * 3. 通过 Freemarker 模板渲染，前后端分离，易于美化。
 */
@Slf4j
public class EasyHtmlLocalReporter implements IReporter {

    // 日期格式化工具，统一报告时间显示格式
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static final String REPORT_FILENAME = "email-report-local.html";

    /**
     * TestNG 调用，生成 HTML 报告主入口
     *
     * @param xmlSuites       TestNG xml 配置
     * @param suites          执行的 suite 列表
     * @param outputDirectory 输出目录（实际被 TestNGUtil 覆盖）
     */
    @Override
    public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
        try {
            // 设置输出路径
            String reportDir = TestNGUtil.getReportDir();
            File dir = new File(reportDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }

            // 创建报告文件
            File reportFile = new File(dir, REPORT_FILENAME);

            // 初始化 Freemarker 配置
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);
            cfg.setClassForTemplateLoading(this.getClass(), "/templates/");
            cfg.setDefaultEncoding("UTF-8");

            // 数据模型准备
            Map<String, Object> dataModel = prepareDataModel(suites);

            // 获取模板
            Template template = cfg.getTemplate("report.ftl");

            // 渲染模板到文件
            try (Writer out = new BufferedWriter(new OutputStreamWriter(
                    Files.newOutputStream(reportFile.toPath()), StandardCharsets.UTF_8))) {
                template.process(dataModel, out);
            }

            log.info("Custom HTML Report generated at: {}", reportFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("Failed to generate custom HTML report", e);
        }
    }

    /**
     * 汇总所有 suite 的测试数据，组装成模板需要的数据结构
     *
     * @param suites TestNG suite 列表
     * @return Map 供 Freemarker 渲染
     */
    private Map<String, Object> prepareDataModel(List<ISuite> suites) {
        Map<String, Object> model = new HashMap<>();

        // 生成时间
        model.put("generationTime", DATE_FORMAT.format(new Date()));

        // suite 列表
        List<Map<String, Object>> suiteList = new ArrayList<>();
        int totalPassed = 0, totalFailed = 0, totalSkipped = 0;

        for (ISuite suite : suites) {
            Map<String, Object> suiteMap = new HashMap<>();
            suiteMap.put("name", suite.getName());

            int passed = 0, failed = 0, skipped = 0;
            List<Map<String, Object>> testClassList = new ArrayList<>();

            for (ISuiteResult result : suite.getResults().values()) {
                ITestContext context = result.getTestContext();

                passed += context.getPassedTests().size();
                failed += context.getFailedTests().size();
                skipped += context.getSkippedTests().size();

                Map<String, Object> testClassMap = new HashMap<>();
                testClassMap.put("className", context.getName());

                List<Map<String, Object>> methodResults = new ArrayList<>();
                Collection<ITestResult> allResults = new ArrayList<>();
                allResults.addAll(context.getPassedTests().getAllResults());
                allResults.addAll(context.getFailedTests().getAllResults());
                allResults.addAll(context.getSkippedTests().getAllResults());

                for (ITestResult res : allResults) {
                    Map<String, Object> resultData = new HashMap<>();
                    String className = res.getTestClass().getRealClass().getSimpleName(); // 简单类名，如 UserServiceTest
                    String methodName = res.getMethod().getMethodName();                  // 方法名，如 test_Reqres_CreateUser
                    String simpleName = className + "." + methodName;
                    resultData.put("methodName", simpleName);
                    resultData.put("status", getStatus(res));
                    resultData.put("statusText", getStatusText(res));
                    resultData.put("startTime", DATE_FORMAT.format(new Date(res.getStartMillis())));
                    resultData.put("duration", res.getEndMillis() - res.getStartMillis());
                    resultData.put("exceptionMessage", getExceptionMessage(res));
                    methodResults.add(resultData);
                }

                testClassMap.put("results", methodResults);
                testClassList.add(testClassMap);
            }

            suiteMap.put("passed", passed);
            suiteMap.put("failed", failed);
            suiteMap.put("skipped", skipped);
            suiteMap.put("total", passed + failed + skipped);
            suiteMap.put("testClasses", testClassList);

            suiteList.add(suiteMap);

            totalPassed += passed;
            totalFailed += failed;
            totalSkipped += skipped;
        }

        model.put("suites", suiteList);
        model.put("totalPassed", totalPassed);
        model.put("totalFailed", totalFailed);
        model.put("totalSkipped", totalSkipped);
        model.put("totalTests", totalPassed + totalFailed + totalSkipped);

        return model;
    }

    /**
     * 获取测试结果状态（pass/fail/skip）
     */
    private String getStatus(ITestResult result) {
        switch (result.getStatus()) {
            case ITestResult.SUCCESS:
                return "pass";
            case ITestResult.FAILURE:
                return "fail";
            case ITestResult.SKIP:
                return "skip";
            default:
                return "unknown";
        }
    }

    /**
     * 获取状态文本（中文）
     */
    private String getStatusText(ITestResult result) {
        switch (result.getStatus()) {
            case ITestResult.SUCCESS:
                return "成功";
            case ITestResult.FAILURE:
                return "失败";
            case ITestResult.SKIP:
                return "跳过";
            default:
                return "未知";
        }
    }

    /**
     * 获取异常信息（如有）
     */
    private String getExceptionMessage(ITestResult result) {
        Throwable t = result.getThrowable();
        if (t != null) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            t.printStackTrace(pw);
            return sw.toString();
        }
        return null;
    }
}